// server/MqttServer.js
import mqtt from 'mqtt';

const client = mqtt.connect('mqtt://mqtt.usr.cn:1883', { username: 'usr.cn', password: 'usr.cn' });
const pollingTimers = {};
const requestDataTypes = new Map();

function crc16(buffer) {
    let crc = 0xFFFF;
    for (let pos = 0; pos < buffer.length; pos++) {
        crc ^= buffer[pos];
        for (let i = 8; i !== 0; i--) {
            if ((crc & 0x0001) !== 0) {
                crc >>= 1;
                crc ^= 0xA001;
            } else {
                crc >>= 1;
            }
        }
    }
    return ((crc & 0xFF) << 8) | ((crc >> 8) & 0xFF);
}

function hexStringToBuffer(hexString) {
    return Buffer.from(hexString.replace(/\s/g, ''), 'hex');
}

function sendCommand(sn, hexCommand) {
    const topic = `youren/${sn}/SubTopic`;
    console.log(`准备发送命令到 ${topic}: ${hexCommand.toString('hex')}`);
    client.publish(topic, hexCommand, { qos: 0 }, (err) => {
        if (err) {
            console.error(`发送命令失败 (${topic}):`, err);
        } else {
            console.log(`命令已成功发送到 ${topic}: ${hexCommand.toString('hex')}`);
        }
    });
}

// 数据类型枚举
const DataType = {
    INT16: 'INT16',
    UINT16: 'UINT16',
    INT32: 'INT32',
    UINT32: 'UINT32',
    FLOAT32_ABCD: 'FLOAT32_ABCD',
    FLOAT32_CDAB: 'FLOAT32_CDAB',
    FLOAT32_BADC: 'FLOAT32_BADC',
    FLOAT32_DCBA: 'FLOAT32_DCBA'
};

// 获取数据类型对应的寄存器数量
function getRegisterCount(dataType) {
    switch (dataType) {
        case DataType.INT16:
        case DataType.UINT16:
            return 1;
        case DataType.INT32:
        case DataType.UINT32:
        case DataType.FLOAT32_ABCD:
        case DataType.FLOAT32_CDAB:
        case DataType.FLOAT32_BADC:
        case DataType.FLOAT32_DCBA:
            return 2;
        default:
            throw new Error('Unsupported data type');
    }
}

// 数据类型转换方法
function convertData(buffer, dataType) {
    switch (dataType) {
        case DataType.INT16:
            return buffer.readInt16BE(0);
        case DataType.UINT16:
            return buffer.readUInt16BE(0);
        case DataType.INT32:
            return buffer.readInt32BE(0);
        case DataType.UINT32:
            return buffer.readUInt32BE(0);
        case DataType.FLOAT32_ABCD:
            return buffer.readFloatBE(0);
        case DataType.FLOAT32_CDAB:
            return Buffer.from([buffer[2], buffer[3], buffer[0], buffer[1]]).readFloatBE(0);
        case DataType.FLOAT32_BADC:
            return Buffer.from([buffer[1], buffer[0], buffer[3], buffer[2]]).readFloatBE(0);
        case DataType.FLOAT32_DCBA:
            return buffer.readFloatLE(0);
        default:
            throw new Error(`Unsupported data type: ${dataType}`);
    }
}

function getSingleData(sn, deviceAddress, functionCode, registerAddress, dataType, pollingInterval = 0) {
    const address = deviceAddress.toString(16).padStart(2, '0');
    const func = functionCode.toString(16).padStart(2, '0');
    const register = registerAddress.toString(16).padStart(4, '0');
    const registerCount = getRegisterCount(dataType);
    const readLength = registerCount.toString(16).padStart(4, '0');
    
    const commandWithoutCRC = `${address}${func}${register}${readLength}`;
    console.log('commandWithoutCRC:', commandWithoutCRC);
    const commandBuffer = hexStringToBuffer(commandWithoutCRC);
    const crc = crc16(commandBuffer);
    const fullCommand = commandWithoutCRC + crc.toString(16).padStart(4, '0');
    const fullCommandBuffer = hexStringToBuffer(fullCommand);
    
    const sendDataCommand = () => {
        console.log(`准备发送数据获取命令: ${fullCommandBuffer.toString('hex')}`);
        sendCommand(sn, fullCommandBuffer);
    };

    sendDataCommand();

    if (pollingInterval > 0) {
        const timerId = `${sn}_${deviceAddress}_${functionCode}_${registerAddress}`;
        if (pollingTimers[timerId]) {
            clearInterval(pollingTimers[timerId]);
        }
        pollingTimers[timerId] = setInterval(sendDataCommand, pollingInterval * 1000);
        console.log(`已设置轮询定时器，间隔 ${pollingInterval} 秒`);
    }
    
    // 存储数据类型信息
    const requestId = `${sn}_${deviceAddress}_${functionCode}_${registerAddress}`;
    requestDataTypes.set(requestId, dataType);
}

function stopPolling(sn, deviceAddress, functionCode, registerAddress) {
    const timerId = `${sn}_${deviceAddress}_${functionCode}_${registerAddress}`;
    if (pollingTimers[timerId]) {
        clearInterval(pollingTimers[timerId]);
        delete pollingTimers[timerId];
        requestDataTypes.delete(timerId);
        console.log(`已停止轮询: ${timerId}`);
    }
}

function stopAllPolling() {
    Object.keys(pollingTimers).forEach(timerId => {
        clearInterval(pollingTimers[timerId]);
        delete pollingTimers[timerId];
        requestDataTypes.delete(timerId);
    });
    console.log('已停止所有轮询');
}

function parseFloat32(hex) {
    const buffer = Buffer.from(hex, 'hex');
    return buffer.readFloatBE(0);
}

function parseMessage(message) {
    const data = message.toString('hex');
    console.log("原始数据:", data);

    if (data.length !== 66) {
        console.error("数据长度不正确");
        return null;
    }

    return {
        address: parseInt(data.substr(0, 2), 16),
        functionCode: parseInt(data.substr(2, 2), 16),
        dataLength: parseInt(data.substr(4, 2), 16),
        voltage: parseFloat32(data.substr(6, 8)).toFixed(2),
        current: parseFloat32(data.substr(14, 8)).toFixed(2),
        activePower: parseFloat32(data.substr(22, 8)).toFixed(2),
        powerFactor: parseFloat32(data.substr(30, 8)).toFixed(2),
        frequency: parseFloat32(data.substr(38, 8)).toFixed(2),
        activeEnergy: parseFloat32(data.substr(46, 8)).toFixed(2),
        switchStatus: parseFloat32(data.substr(54, 8)).toFixed(2),
        rawData: data
    };
}

function sendTestCommand(sn) {
    const commandWithoutCRC = '0104012C000E';
    const commandBuffer = hexStringToBuffer(commandWithoutCRC);
    const crc = crc16(commandBuffer);
    const fullCommand = commandWithoutCRC + crc.toString(16).padStart(4, '0');
    const fullCommandBuffer = hexStringToBuffer(fullCommand);
    
    console.log('准备发送测试命令:', fullCommandBuffer.toString('hex'));
    sendCommand(sn, fullCommandBuffer);
}

function sendInitialMessage(sn) {
    const topic = `youren/${sn}/SubTopic`;
    const commandWithoutCRC = '0104012C000E';
    const commandBuffer = hexStringToBuffer(commandWithoutCRC);
    const crc = crc16(commandBuffer);
    const fullCommand = commandWithoutCRC + crc.toString(16).padStart(4, '0');
    const fullCommandBuffer = hexStringToBuffer(fullCommand);
    
    console.log(`准备发送初始消息到 ${topic}: ${fullCommandBuffer.toString('hex')}`);
    client.publish(topic, fullCommandBuffer, { qos: 0, retain: false }, (err) => {
        if (err) {
            console.error(`发送初始消息失败 (${topic}):`, err);
        } else {
            console.log(`初始消息已成功发送到 ${topic}: ${fullCommandBuffer.toString('hex')}`);
        }
    });
}

function getVoltageParameter(sn) {
    const deviceAddress = 1;
    const functionCode = 4;
    const registerAddress = 0x0190;
    const dataType = DataType.FLOAT32_ABCD;
    const pollingInterval = 1;

    getSingleData(sn, deviceAddress, functionCode, registerAddress, dataType, pollingInterval);
}

client.on('connect', () => {
    console.log('MQTT 客户端已连接');
});

client.on('message', (topic, message) => {
    console.log(`收到来自主题 ${topic} 的原始消息:`, message.toString('hex'));
    try {
        console.log('message.length:', message.length);
        const data = message.toString('hex');
        const address = parseInt(data.substr(0, 2), 16);
        const functionCode = parseInt(data.substr(2, 2), 16);
        const byteCount = parseInt(data.substr(4, 2), 16);
        const valueHex = data.substr(6, byteCount * 2);
        console.log('valueHex:', valueHex);
        const valueBuffer = Buffer.from(valueHex, 'hex');

        const sn = topic.split('/')[1];
        
        // 查找匹配的请求ID
        let matchingRequestId = null;
        for (const [requestId, dataType] of requestDataTypes.entries()) {
            const [reqSn, reqAddress, reqFunctionCode] = requestId.split('_');
            if (reqSn === sn && parseInt(reqAddress) === address && parseInt(reqFunctionCode) === functionCode) {
                matchingRequestId = requestId;
                break;
            }
        }

        if (matchingRequestId) {
            const dataType = requestDataTypes.get(matchingRequestId);
            const value = convertData(valueBuffer, dataType);
            console.log(`解析的数值 (${dataType}):`, value);
            // 可以在这里添加进一步的处理逻辑
        } else {
            console.log('未找到匹配的请求，无法解析数据');
        }
    } catch (error) {
        console.error('解析消息时出错:', error);
    }
});

client.on('error', (error) => {
    console.error('MQTT 错误:', error);
});

client.on('close', () => {
    console.log('MQTT 客户端连接已关闭');
});

client.on('reconnect', () => {
    console.log('MQTT 客户端正在重新连接');
});

export default {
    client,
    sendCommand,
    getSingleData,
    stopPolling,
    stopAllPolling,
    sendTestCommand,
    sendInitialMessage,
    getVoltageParameter,
    DataType
};